﻿// -----------------------------------------------------------------------
// <copyright file="DTSDimension.cs" company="">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

namespace WMM.Tapioca.Taxonomy
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using WMM.Tapioca.XbrlDimension;
    using WMM.Tapioca.Linkbase;

    /// <summary>
    /// TODO: Update summary.
    /// </summary>
    public class DTSDimension
    {
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        private DTS dts;

        #region Dimensional properties

        private List<Hypercube> hypercubes;

        /// <summary>
        /// Represents a list of hypercube declaration.
        /// </summary>
        public List<Hypercube> Hypercubes
        {
            get { return hypercubes; }
            set { hypercubes = value; }
        }

        private List<Dimension> dimensions;

        /// <summary>
        /// Represents a list of dimension declaration.
        /// </summary>
        public List<Dimension> Dimensions
        {
            get { return dimensions; }
            set { dimensions = value; }
        }

        private DictionaryMap<HasHypercube> hasHypercubes;

        /// <summary>
        /// Represents a list of HasHypercube relationships.
        /// </summary>
        public DictionaryMap<HasHypercube> HasHypercubes
        {
            get { return hasHypercubes; }
            set { hasHypercubes = value; }
        }

        private DictionaryMap<HypercubeDimension> hypercubeDimensions;

        /// <summary>
        /// Represents a list of HypercubeDimension relationships.
        /// </summary>
        public DictionaryMap<HypercubeDimension> HypercubeDimensions
        {
            get { return hypercubeDimensions; }
            set { hypercubeDimensions = value; }
        }

        private DictionaryMap<DimensionDomain> dimensionDomains;

        /// <summary>
        /// Represents a list of DimensionDomain relationships.
        /// </summary>
        public DictionaryMap<DimensionDomain> DimensionDomains
        {
            get { return dimensionDomains; }
            set { dimensionDomains = value; }
        }

        private DictionaryMap<DimensionDefault> dimensionDefaults;

        public DictionaryMap<DimensionDefault> DimensionDefaults
        {
            get { return dimensionDefaults; }
            set { dimensionDefaults = value; }
        }

        private DictionaryMap<DomainMember> domainMembers;

        /// <summary>
        /// Represents a list of DomainMemberBaseSet.
        /// </summary>
        public DictionaryMap<DomainMember> DomainMembers
        {
            get { return domainMembers; }
            set { domainMembers = value; }
        }

        private DictionaryMap<DomainMemberBaseSet> domainMemberBaseSets;

        /// <summary>
        /// Represents a list of DomainMemberBaseSet.
        /// </summary>
        public DictionaryMap<DomainMemberBaseSet> DomainMemberBaseSets
        {
            get { return domainMemberBaseSets; }
            set { domainMemberBaseSets = value; }
        }

        private List<Inheritance> inheritances;

        /// <summary>
        /// Represents a list of Inheritance primary itens.
        /// </summary>
        public List<Inheritance> Inheritances
        {
            get { return inheritances; }
            set { inheritances = value; }
        }

        private List<DimensionalRelationshipSet> dimensionalRelationshipSets;

        /// <summary>
        /// Represents a list of DimensionalRelationshipSet.
        /// </summary>
        public List<DimensionalRelationshipSet> DimensionalRelationshipSets
        {
            get { return dimensionalRelationshipSets; }
            set { dimensionalRelationshipSets = value; }
        }

        #endregion

        /// <summary>
        /// The constructor.
        /// </summary>
        public DTSDimension(DTS dtsXbrl)
        {
            Controller.Instance.RaiseModelChange(this, new ModelChangeEventArgs("Building DTSDimension..."));

            dts = dtsXbrl;

            // Dimensional 
            hypercubes = new List<Hypercube>();
            dimensions = new List<Dimension>();
            hasHypercubes = new DictionaryMap<HasHypercube>();
            hypercubeDimensions = new DictionaryMap<HypercubeDimension>();
            dimensionDomains = new DictionaryMap<DimensionDomain>();
            dimensionDefaults = new DictionaryMap<DimensionDefault>();
            domainMembers = new DictionaryMap<DomainMember>();
            domainMemberBaseSets = new DictionaryMap<DomainMemberBaseSet>();
            Inheritances = new List<Inheritance>();

            // Build Dimensional Taxonomy
            BuildDimensionalTaxonomy();
            DiscoveryDimensionalRelationshipSets();
            BuildDimensionalRelationshipSets();
        }


        #region DimensionalTaxonomy

        private void BuildDimensionalTaxonomy()
        {
            Controller.Instance.RaiseModelChange(this, new ModelChangeEventArgs("Building Dimensional Taxonomy..."));

            foreach (TaxonomySchema taxonomySchema in dts.TaxonomySchemas)
            {
                foreach (Concept concept in taxonomySchema.Concepts)
                {
                    if (concept.SubstitutionGroup == Concept.EnumSubstitutionGroup.HypercubeItem)
                    {
                        hypercubes.Add(new Hypercube(concept));
                    }

                    else if (concept.SubstitutionGroup == Concept.EnumSubstitutionGroup.DimensionItem)
                    {
                        dimensions.Add(new Dimension(concept));
                    }
                    else
                    {
                        if (concept.SubstitutionGroup == Concept.EnumSubstitutionGroup.Unknown)
                        {
                            Concept otherConcept = dts.GetConceptByName(concept.SchemaElement.SubstitutionGroup.Name);

                            if (otherConcept != null)
                            {
                                if (otherConcept.SubstitutionGroup == Concept.EnumSubstitutionGroup.HypercubeItem)
                                {
                                    hypercubes.Add(new Hypercube(concept));
                                }

                                if (otherConcept.SubstitutionGroup == Concept.EnumSubstitutionGroup.DimensionItem)
                                {
                                    dimensions.Add(new Dimension(concept));
                                }
                            }
                        }
                    }
                }
            }
        }


        private void DiscoveryDimensionalRelationshipSets()
        {
            Controller.Instance.RaiseModelChange(this, new ModelChangeEventArgs("Building Dimensional Relationship Sets..."));

            foreach (NetworkGraph networkGraph in dts.NetworkGraphs)
            {
                if (networkGraph.TupleNG.Item1.Equals("definitionLink"))
                {
                    if (dts.IsCustomArcRole(networkGraph.TupleNG.Item4))
                    {
                        ArcRoleType arcRoleType = dts.GetArcRoleType(networkGraph.TupleNG.Item4);

                        DiscoveryHasHypercubeArcs(networkGraph, arcRoleType);
                    }
                }
            }

            foreach (NetworkGraph networkGraph in dts.NetworkGraphs)
            {
                if (networkGraph.TupleNG.Item1.Equals("definitionLink"))
                {
                    if (dts.IsCustomArcRole(networkGraph.TupleNG.Item4))
                    {
                        ArcRoleType arcRoleType = dts.GetArcRoleType(networkGraph.TupleNG.Item4);

                        DiscoveryHypercubeDimensionArcs(networkGraph, arcRoleType);
                    }
                }
            }

            foreach (NetworkGraph networkGraph in dts.NetworkGraphs)
            {
                if (networkGraph.TupleNG.Item1.Equals("definitionLink"))
                {
                    if (dts.IsCustomArcRole(networkGraph.TupleNG.Item4))
                    {
                        ArcRoleType arcRoleType = dts.GetArcRoleType(networkGraph.TupleNG.Item4);
                        DiscoveryDimensionDomainArcs(networkGraph, arcRoleType);
                    }
                }
            }

            foreach (NetworkGraph networkGraph in dts.NetworkGraphs)
            {
                if (networkGraph.TupleNG.Item1.Equals("definitionLink"))
                {
                    if (dts.IsCustomArcRole(networkGraph.TupleNG.Item4))
                    {
                        ArcRoleType arcRoleType = dts.GetArcRoleType(networkGraph.TupleNG.Item4);
                        DiscoveryDomainMemberArcs(networkGraph, arcRoleType);
                    }
                }
            }

            foreach (NetworkGraph networkGraph in dts.NetworkGraphs)
            {
                if (networkGraph.TupleNG.Item1.Equals("definitionLink"))
                {
                    if (dts.IsCustomArcRole(networkGraph.TupleNG.Item4))
                    {
                        ArcRoleType arcRoleType = dts.GetArcRoleType(networkGraph.TupleNG.Item4);
                        DiscoveryDimensionDefaultArcs(networkGraph, arcRoleType);
                    }

                }

            }

        }


        private void DiscoveryHasHypercubeArcs(NetworkGraph networkGraph, ArcRoleType arcRoleType)
        {
            if (arcRoleType.Id.Equals("all") || (arcRoleType.Id.Equals("notAll")))
            {
                foreach (Arc arc in networkGraph.NetworkRelationships)
                {
                    HasHypercube hasHypercube = new HasHypercube(networkGraph.TupleNG.Item4);

                    Locator locTo = dts.GetLocator(arc.ExtendedLinkParent.Locators, arc.ToId);

                    Hypercube hypercube = GetHypercubeById(locTo.HrefResourceId);

                    if (hypercube != null)
                    {
                        hasHypercube.Hypercube = hypercube;
                        hasHypercube.SourceRole = networkGraph.TupleNG.Item2;
                        hasHypercube.TargetRole = arc.TargetRole;
                        hasHypercube.EffectiveRole = (arc.TargetRole == null ? hasHypercube.SourceRole : hasHypercube.TargetRole.AbsoluteUri);
                        hasHypercube.ArcCR = arc;
                        hasHypercube.ContextElement = arc.ContextElement;
                        bool summable;
                        Boolean.TryParse(arc.Summable == null ? "false" : arc.Summable, out summable);
                        hasHypercube.Summable = summable;
                        bool closed;
                        Boolean.TryParse(arc.Closed == null ? "false" : arc.Closed, out closed);
                        hasHypercube.Closed = closed;
                        Locator locFrom = dts.GetLocator(arc.ExtendedLinkParent.Locators, arc.FromId);
                        hasHypercube.PrimaryItem = dts.GetConceptByID(locFrom.HrefResourceId);
                        hasHypercube.LocatorPrimaryItem = locFrom;
                    }

                    hasHypercubes.Add(networkGraph.TupleNG.Item2, hasHypercube);
                }
            }
        }


        private void DiscoveryHypercubeDimensionArcs(NetworkGraph networkGraph, ArcRoleType arcRoleType)
        {
            if (arcRoleType.Id.Equals("hypercube-dimension"))
            {
                foreach (Arc arc in networkGraph.NetworkRelationships)
                {
                    HypercubeDimension hypercubeDimension = new HypercubeDimension();

                    Locator locatorFrom = dts.GetLocator(arc.ExtendedLinkParent.Locators, arc.FromId);
                    Hypercube hypercube = GetHypercubeById(locatorFrom.HrefResourceId);
                    HasHypercube hasHypercube = GetHasHypercubeById(locatorFrom.HrefResourceId);

                    if (hypercube != null)
                    {
                        hypercubeDimension.Hypercube = hypercube;
                        hypercubeDimension.SourceRole = networkGraph.TupleNG.Item2;
                        hypercubeDimension.TargetRole = arc.TargetRole;
                        hypercubeDimension.EffectiveRole = (arc.TargetRole == null ? hypercubeDimension.SourceRole : hypercubeDimension.TargetRole.AbsoluteUri);
                        hypercubeDimension.ArcCR = arc;
                        bool summable;
                        Boolean.TryParse(arc.Summable == null ? "false" : arc.Summable, out summable);
                        hypercubeDimension.Summable = summable;

                        Locator locatorTo = dts.GetLocator(arc.ExtendedLinkParent.Locators, arc.ToId);
                        Dimension dimension = GetDimensionById(locatorTo.HrefResourceId);

                        if (dimension != null)
                        {
                            hypercubeDimension.Dimension = dimension;
                        }
                    }

                    hypercubeDimensions.Add(networkGraph.TupleNG.Item2, hypercubeDimension);
                }
            }
        }


        private void DiscoveryDimensionDomainArcs(NetworkGraph networkGraph, ArcRoleType arcRoleType)
        {
            if (arcRoleType.Id.Equals("dimension-domain"))
            {
                foreach (Arc arc in networkGraph.NetworkRelationships)
                {
                    DimensionDomain dimensionDomain = new DimensionDomain();

                    Locator locatorFrom = dts.GetLocator(arc.ExtendedLinkParent.Locators, arc.FromId);
                    Dimension dimension = GetDimensionById(locatorFrom.HrefResourceId);

                    if (dimension != null)
                    {
                        dimensionDomain.Dimension = dimension;

                        Locator locatorTo = dts.GetLocator(arc.ExtendedLinkParent.Locators, arc.ToId);
                        Concept conceptTo = dts.GetConceptByID(locatorTo.HrefResourceId);
                        //dimension.Domains.Add(conceptTo);

                        dimensionDomain.Domain = new Domain(conceptTo, dimension);
                        dimensionDomain.SourceRole = networkGraph.TupleNG.Item2;
                        dimensionDomain.TargetRole = arc.TargetRole;
                        dimensionDomain.EffectiveRole = (arc.TargetRole == null ? dimensionDomain.SourceRole : dimensionDomain.TargetRole.AbsoluteUri);
                        dimensionDomain.ArcCR = arc;
                        dimensionDomain.Usable = Boolean.Parse(arc.Usable == null ? "true" : arc.Usable);
                    }

                    dimensionDomains.Add(networkGraph.TupleNG.Item2, dimensionDomain);
                }
            }
        }


        private void DiscoveryDomainMemberArcs(NetworkGraph networkGraph, ArcRoleType arcRoleType)
        {
            if (arcRoleType.Id.Equals("domain-member"))
            {
                DomainMemberBaseSet domainMemberBaseSet = new DomainMemberBaseSet();
                domainMemberBaseSet.NetworkGraph = networkGraph;

                foreach (Arc arc in networkGraph.NetworkRelationships)
                {
                    Locator locatorFrom = dts.GetLocator(arc.ExtendedLinkParent.Locators, arc.FromId);
                    Locator locatorTo = dts.GetLocator(arc.ExtendedLinkParent.Locators, arc.ToId);
                    Concept conceptFrom = dts.GetConceptByID(locatorFrom.HrefResourceId);
                    Concept conceptTo = dts.GetConceptByID(locatorTo.HrefResourceId);

                    DomainMember domainMember = new DomainMember(conceptFrom, conceptTo);
                    domainMember.SourceRole = networkGraph.TupleNG.Item2;
                    domainMember.TargetRole = arc.TargetRole;
                    domainMember.EffectiveRole = (arc.TargetRole == null ? domainMember.SourceRole : domainMember.TargetRole.AbsoluteUri);
                    domainMember.ArcCR = arc;
                    bool usable;
                    Boolean.TryParse(arc.Usable == null ? "true" : arc.Usable, out usable);
                    domainMember.Usable = usable;

                    domainMembers.Add(networkGraph.TupleNG.Item2, domainMember);
                    domainMemberBaseSet.DomainMembers.Add(domainMember);
                }

                domainMemberBaseSets.Add(networkGraph.TupleNG.Item2, domainMemberBaseSet);
            }
        }


        private void DiscoveryDimensionDefaultArcs(NetworkGraph networkGraph, ArcRoleType arcRoleType)
        {
            if (arcRoleType.Id.Equals("dimension-default"))
            {
                DimensionDefault dimensionDefault = new DimensionDefault();

                foreach (Arc arc in networkGraph.NetworkRelationships)
                {
                    Concept conceptTo = dts.GetConceptByID(arc.ToLocator.HrefResourceId); // default member
                    Dimension dimension = GetDimensionById(arc.FromLocator.HrefResourceId);

                    if (dimension != null)
                    {
                        dimensionDefault.Dimension = dimension;
                        dimensionDefault.DefaultValue = conceptTo;
                        dimensionDefault.SourceRole = networkGraph.TupleNG.Item2;
                        dimensionDefault.ArcCR = arc;

                        dimension.DefaultConcept = conceptTo;
                        dimension.DefaultDimensionArc = arc;
                        // to draw a graph
                        dimension.DefaultDimensionRole = networkGraph.TupleNG.Item2;
                    }
                }

                dimensionDefaults.Add(networkGraph.TupleNG.Item2, dimensionDefault);
            }
        }



        private void BuildDimensionalRelationshipSets()
        {
            Controller.Instance.RaiseModelChange(this, new ModelChangeEventArgs("Building DimensionalRelationshipSets2..."));

            dimensionalRelationshipSets = new List<DimensionalRelationshipSet>();

            foreach (string roleSourceDRS in hasHypercubes.Keys)
            {
                DimensionalRelationshipSet drs = new DimensionalRelationshipSet();
                drs.DRSRole = roleSourceDRS;

                List<HasHypercube> hasHypercubeList = hasHypercubes[roleSourceDRS];

                foreach (HasHypercube hasHypercube in hasHypercubeList)
                {
                    ConsecutiveRelationshipsSet crs = new ConsecutiveRelationshipsSet();
                    crs.HasHypercube = hasHypercube;
                    drs.ArcRelationshipSet.Add(hasHypercube.ArcCR);

                    // Search for consecutive relationships 'hypercubeDimension' and add it to DRS.

                    SearchConsecutiveRelationshipsHypercubeDimension(drs, hasHypercube, crs);

                    // Search for consecutive relationships 'dimensionDomain' and add it to DRS. 

                    SearchConsecutiveRelationshipsDimensionDomain(drs, crs);

                    // Search for consecutive relationships 'dimensionDefault' and add it to DRS. 

                    SearchConsecutiveRelationshipsDimensionDefault(drs, crs);

                    // Search for consecutive relationships 'DomainMember' and add it to DRS. 

                    SearchConsecutiveRelationshipsDomainMember(drs, crs);

                    drs.ConsecutiveRelationshipsSets.Add(crs);
                }

                dimensionalRelationshipSets.Add(drs);
            }

            DiscoveryPrimaryItemsInherited();
            //BuildDRSInherited();
        }


        private void DiscoveryPrimaryItemsInherited()
        {
            foreach (DimensionalRelationshipSet drs in DimensionalRelationshipSets)
            {
                //List<Concept> distinctPrimaryItems = GetDistinctPrimaryItems(drs.ConsecutiveRelationshipsSets);
                IEnumerable<Concept> distinctPrimaryItems = drs.ConsecutiveRelationshipsSets.Select(p => p.HasHypercube.PrimaryItem).Distinct();

                foreach (Concept primaryItem in distinctPrimaryItems)
                {
                    //List<Concept> conceptsInherited = new List<Concept>();

                    Inheritance inheritance = new Inheritance();
                    inheritance.PrimaryItem = primaryItem;

                    List<Concept> conceptsInherited = GetAllDescendents3(primaryItem, drs.DRSRole);

                    //List<DomainMember> domainMembers = GetDomainMembers(primaryItem, drs.DRSRole);

                    //foreach (DomainMember domainMember in domainMembers)
                    //{
                    //    if (domainMember.TargetRole != null)
                    //    {
                    //        //DomainMember domainMemberT = GetDomainMember(domainMember.Member, domainMember.TargetRole.AbsoluteUri);
                    //        Locator locatorTo = GetLocator(domainMember.ArcCR.ExtendedLinkParent.ParentDocument, domainMember.Member.Id, domainMember.TargetRole.AbsoluteUri);

                    //        if (locatorTo != null)
                    //        {
                    //            inheritance.SourceRole = drs.DRSRole;
                    //            inheritance.TargetRole = domainMember.TargetRole;
                    //            conceptsInherited.Add(domainMember.Member);
                    //            conceptsInherited.AddRange(GetAllDescendents(locatorTo, "http://xbrl.org/int/dim/arcrole/domain-member"));
                    //        }
                    //    }
                    //    else
                    //    {
                    //        inheritance.SourceRole = drs.DRSRole;
                    //        conceptsInherited.Add(domainMember.Member);
                    //        conceptsInherited.AddRange(GetAllDescendents(domainMember.ArcCR.ToLocator, "http://xbrl.org/int/dim/arcrole/domain-member"));                            
                    //    }
                    //}

                    //List<DomainMember> domainMembersOut = GetDomainMembersOut(primaryItem, drs.DRSRole);

                    //foreach (DomainMember domainMember in domainMembersOut)
                    //{
                    //    inheritance.SourceRole = domainMember.SourceRole;
                    //    conceptsInherited.Add(domainMember.Domain);
                    //    conceptsInherited.AddRange(GetAllDescendents(domainMember.ArcCR.FromLocator, "http://xbrl.org/int/dim/arcrole/domain-member"));
                    //}

                    if (conceptsInherited.Count > 0)
                    {
                        inheritance.SourceRole = drs.DRSRole;
                        //inheritance.TargetRole = domainMember.TargetRole;
                        inheritance.PrimaryItemsInherited.AddRange(conceptsInherited);

                        inheritances.Add(inheritance);
                    }
                }
            }
        }


        private List<Concept> GetAllDescendents3(Concept member, string sourceRole)
        {
            List<Concept> members = new List<Concept>();

            //foreach (string roleDomainMember in DomainMembers.Keys)
            //{
            List<DomainMember> domainMemberList = DomainMembers[sourceRole];

            foreach (DomainMember domainMember in domainMemberList)
            {
                if (domainMember.Domain.Id.Equals(member.Id))
                {
                    if (!members.Contains(domainMember.Member))
                    {
                        members.Add(domainMember.Member);

                        if (domainMember.TargetRole != null)
                        {
                            members.AddRange(GetAllDescendents3(domainMember.Member, domainMember.TargetRole.AbsoluteUri));
                        }
                        else
                        {
                            members.AddRange(GetAllDescendents3(domainMember.Member, sourceRole));
                        }
                    }
                }
            }
            //}

            return members;
        }


        private List<DomainMember> GetDomainMembersOut(Concept concept, string sourceRole)
        {
            List<DomainMember> domainMembers = new List<DomainMember>();

            foreach (string roleDomainMember in DomainMembers.Keys)
            {
                List<DomainMember> domainMemberList = DomainMembers[roleDomainMember];

                foreach (DomainMember domainMember in domainMemberList)
                {
                    if (domainMember.Member.Id.Equals(concept.Id) && !domainMember.ArcCR.ExtendedLinkRole.Equals(sourceRole))
                    {
                        domainMembers.Add(domainMember);
                    }
                }
            }

            return domainMembers;
        }


        private Locator GetLocator(XbrlDocument document, string id, string roleBaseSet)
        {
            Locator locator = null;
            LinkbaseDocument linkbase = document as LinkbaseDocument;

            foreach (ExtendedLink extendedLink in linkbase.ExtendedLinks)
            {
                if (extendedLink.ExtendedLinkRole.Equals(roleBaseSet))
                {
                    foreach (Locator loc in extendedLink.Locators)
                    {
                        if (loc.HrefResourceId.Equals(id))
                        {
                            locator = loc;
                        }
                    }
                }
            }

            return locator;
        }


        private void DiscoveryPrimaryItemsInherited2()
        {
            foreach (NetworkGraph networkGraph in dts.NetworkGraphs)
            {
                if (networkGraph.TupleNG.Item1.Equals("definitionLink"))
                {
                    if (networkGraph.TupleNG.Item4.Equals("http://xbrl.org/int/dim/arcrole/domain-member"))
                    {
                        foreach (Arc arc in networkGraph.NetworkRelationships)
                        {
                            Locator locatorFrom = dts.GetLocator(arc.ExtendedLinkParent.Locators, arc.FromId);
                            Locator locatorTo = dts.GetLocator(arc.ExtendedLinkParent.Locators, arc.ToId);
                            Concept conceptFrom = dts.GetConceptByID(locatorFrom.HrefResourceId);
                            Concept conceptTo = dts.GetConceptByID(locatorTo.HrefResourceId);

                            if (IsPrimaryItemRootOfDRS(conceptFrom))
                            {
                                Inheritance inheritance = new Inheritance();
                                inheritance.PrimaryItem = conceptFrom;
                                List<Concept> conceptsInherited = GetAllDescendents(arc.FromLocator, "http://xbrl.org/int/dim/arcrole/domain-member");
                                inheritance.PrimaryItemsInherited.AddRange(conceptsInherited);
                                inheritances.Add(inheritance);
                            }
                        }
                    }
                }
            }
        }


        private List<Concept> GetDistinctPrimaryItems(List<ConsecutiveRelationshipsSet> crsList)
        {
            List<Concept> distinctItems = new List<Concept>();

            foreach (ConsecutiveRelationshipsSet crs in crsList)
            {
                crsList.Select(p => p.HasHypercube.PrimaryItem).Distinct();
            }

            return distinctItems;
        }


        private void BuildDRSInherited()
        {
            List<DimensionalRelationshipSet> dimensionalRelationshipSets2 = new List<DimensionalRelationshipSet>();

            foreach (Inheritance inheritance in Inheritances)
            {
                foreach (Concept primaryItemInherited in inheritance.PrimaryItemsInherited)
                {
                    ConsecutiveRelationshipsSet crs = GetConsecutiveRelationshipsSet(inheritance.PrimaryItem);

                    DimensionalRelationshipSet drs = new DimensionalRelationshipSet();
                    drs.ConsecutiveRelationshipsSets.Add(crs);
                    drs.DRSRole = primaryItemInherited.Name;


                    dimensionalRelationshipSets2.Add(drs);

                }
            }

            dimensionalRelationshipSets.AddRange(dimensionalRelationshipSets2);
        }


        private ConsecutiveRelationshipsSet GetConsecutiveRelationshipsSet(Concept concept)
        {
            foreach (DimensionalRelationshipSet drs in DimensionalRelationshipSets)
            {
                foreach (ConsecutiveRelationshipsSet crs in drs.ConsecutiveRelationshipsSets)
                {
                    if (concept.Id.Equals(crs.HasHypercube.PrimaryItem.Id))
                    {
                        return crs;
                    }
                }
            }

            return null;
        }


        private List<Concept> GetAllAncestors(Concept member, List<DomainMember> domainMemberList)
        {
            List<Concept> members = new List<Concept>();

            foreach (DomainMember domainMember in domainMemberList)
            {
                if (domainMember.Member.Id.Equals(member.Id))
                {
                    members.Add(domainMember.Domain);
                    members.AddRange(GetAllAncestors(domainMember.Domain, domainMemberList));
                }
            }

            return members;
        }


        private void SearchConsecutiveRelationshipsHypercubeDimension(DimensionalRelationshipSet drs, HasHypercube hasHypercube, ConsecutiveRelationshipsSet crs)
        {
            foreach (string roleHypercubeDimension in HypercubeDimensions.Keys)
            {
                List<HypercubeDimension> hypercubeDimensionList = HypercubeDimensions[roleHypercubeDimension];

                foreach (HypercubeDimension hypercubeDimension in hypercubeDimensionList)
                {
                    if (hasHypercube.Hypercube.Concept.Id.Equals(hypercubeDimension.Hypercube.Concept.Id) && (hasHypercube.TargetRole == null ?
                        hasHypercube.SourceRole.Equals(hypercubeDimension.SourceRole) :
                        hasHypercube.TargetRole.Equals(hypercubeDimension.SourceRole)))
                    {
                        crs.HypercubeDimensions.Add(hypercubeDimension);
                        drs.ArcRelationshipSet.Add(hypercubeDimension.ArcCR);
                    }
                }
            }
        }


        private void SearchConsecutiveRelationshipsDimensionDomain(DimensionalRelationshipSet drs, ConsecutiveRelationshipsSet crs)
        {
            foreach (HypercubeDimension hypercubeDimensionDRS in crs.HypercubeDimensions)
            {
                foreach (string roleDimensionDomain in DimensionDomains.Keys)
                {
                    List<DimensionDomain> dimensionDomainList = DimensionDomains[roleDimensionDomain];

                    foreach (DimensionDomain dimensionDomain in dimensionDomainList)
                    {
                        if (hypercubeDimensionDRS.Dimension.Concept.Id.Equals(dimensionDomain.Dimension.Concept.Id) && (hypercubeDimensionDRS.TargetRole == null ?
                            hypercubeDimensionDRS.SourceRole.Equals(dimensionDomain.SourceRole) :
                            hypercubeDimensionDRS.TargetRole.Equals(dimensionDomain.SourceRole)))
                        {
                            crs.DimensionDomains.Add(dimensionDomain);
                            crs.Members.Add(dimensionDomain.Domain.Concept);
                            drs.ArcRelationshipSet.Add(dimensionDomain.ArcCR);
                        }
                    }
                }
            }
        }


        private void SearchConsecutiveRelationshipsDimensionDefault(DimensionalRelationshipSet drs, ConsecutiveRelationshipsSet crs)
        {
            foreach (HypercubeDimension hypercubeDimensionDRS in crs.HypercubeDimensions)
            {
                foreach (string roleDimensionDefault in DimensionDefaults.Keys)
                {
                    List<DimensionDefault> dimensionDefaultList = DimensionDefaults[roleDimensionDefault];

                    foreach (DimensionDefault dimensionDefault in dimensionDefaultList)
                    {
                        if (hypercubeDimensionDRS.Dimension.Concept.Id.Equals(dimensionDefault.Dimension.Concept.Id) && (hypercubeDimensionDRS.TargetRole == null ?
                            hypercubeDimensionDRS.SourceRole.Equals(dimensionDefault.SourceRole) :
                            hypercubeDimensionDRS.TargetRole.Equals(dimensionDefault.SourceRole)))
                        {
                            crs.DimensionDefaults.Add(dimensionDefault);
                            drs.ArcRelationshipSet.Add(dimensionDefault.ArcCR);
                        }
                    }
                }
            }
        }


        private void SearchConsecutiveRelationshipsDomainMember(DimensionalRelationshipSet drs, ConsecutiveRelationshipsSet crs)
        {
            foreach (DimensionDomain dimensionDomainDRS in crs.DimensionDomains)
            {
                foreach (string roleDomainMember in DomainMembers.Keys)
                {
                    List<DomainMember> domainMemberList = DomainMembers[roleDomainMember];

                    foreach (DomainMember domainMember in domainMemberList)
                    {
                        if (dimensionDomainDRS.Domain.Concept.Id.Equals(domainMember.Domain.Id) && (dimensionDomainDRS.TargetRole == null ?
                            dimensionDomainDRS.SourceRole.Equals(domainMember.SourceRole) :
                            dimensionDomainDRS.TargetRole.Equals(domainMember.SourceRole)))
                        {
                            crs.DomainMembers.Add(domainMember);
                            crs.Members.Add(domainMember.Member);
                            drs.ArcRelationshipSet.Add(domainMember.ArcCR);

                            if (domainMember.TargetRole == null && domainMember.Usable)
                            {
                                crs.DomainMembers.AddRange(GetAllDescendents(domainMember.Member, domainMemberList));
                                crs.Members.AddRange(GetAllDescendents2(domainMember.Member, domainMemberList));
                            }

                            if (domainMember.TargetRole != null)
                            {
                                if (DomainMembers.Keys.Contains(domainMember.TargetRole.AbsoluteUri))
                                {
                                    List<DomainMember> domainMembersTargetRole = DomainMembers[domainMember.TargetRole.AbsoluteUri];

                                    foreach (DomainMember domainMemberTargetRole in domainMembersTargetRole)
                                    {
                                        //if (dimensionDomainDRS.Domain.Concept.Id.Equals(domainMemberTargetRole.Domain.Id))
                                        //{

                                        if (domainMemberTargetRole.Usable)
                                        {
                                            crs.DomainMembers.Add(domainMemberTargetRole);
                                            crs.DomainMembers.AddRange(GetAllDescendents(domainMemberTargetRole.Member, domainMembersTargetRole));

                                            drs.ArcRelationshipSet.Add(domainMemberTargetRole.ArcCR);

                                            crs.Members.Add(domainMemberTargetRole.Member);
                                            crs.Members.AddRange(GetAllDescendents2(domainMemberTargetRole.Member, domainMembersTargetRole));
                                        }
                                        //}
                                    }
                                }
                            }
                        }


                    }
                }
            }
        }


        private List<DomainMember> GetAllDescendents(Concept member, List<DomainMember> domainMemberList)
        {
            List<DomainMember> domainMembers = new List<DomainMember>();

            foreach (DomainMember domainMember in domainMemberList)
            {
                if (domainMember.Domain.Id.Equals(member.Id))
                {
                    if (!domainMembers.Contains(domainMember))
                    {
                        domainMembers.Add(domainMember);
                        domainMembers.AddRange(GetAllDescendents(domainMember.Member, domainMemberList));
                    }
                }
            }

            return domainMembers;
        }


        private List<Concept> GetAllDescendents2(Concept member, List<DomainMember> domainMemberList)
        {
            List<Concept> members = new List<Concept>();

            foreach (DomainMember domainMember in domainMemberList)
            {
                if (domainMember.Domain.Id.Equals(member.Id))
                {
                    if (!members.Contains(domainMember.Member))
                    {
                        members.Add(domainMember.Member);
                        members.AddRange(GetAllDescendents2(domainMember.Member, domainMemberList));
                    }
                }
            }

            return members;
        }

        private List<Concept> GetAllDescendents(Locator locator, string arcRole)
        {
            List<Concept> descendents = new List<Concept>();

            foreach (Arc arc in locator.OutArcs)
            {
                if (arc.ArcRole.AbsoluteUri.Equals(arcRole) && arc.TargetRole == null)
                {
                    Concept concept = dts.GetConceptByID(arc.ToLocator.HrefResourceId);
                    descendents.Add(concept);
                    descendents.AddRange(GetAllDescendents(arc.ToLocator, arcRole));
                }
            }

            return descendents;
        }


        private List<DomainMember> GetDomainMembers(Concept concept, string sourceRole)
        {
            List<DomainMember> domainMembers = new List<DomainMember>();

            foreach (string roleDomainMember in DomainMembers.Keys)
            {
                List<DomainMember> domainMemberList = DomainMembers[roleDomainMember];

                foreach (DomainMember domainMember in domainMemberList)
                {
                    if (domainMember.Domain.Id.Equals(concept.Id) && domainMember.ArcCR.ExtendedLinkRole.Equals(sourceRole))
                    {
                        domainMembers.Add(domainMember);
                    }
                }
            }

            return domainMembers;
        }


        private DomainMember GetDomainMember(Concept concept, string sourceRole)
        {
            foreach (string roleDomainMember in DomainMembers.Keys)
            {
                List<DomainMember> domainMemberList = DomainMembers[roleDomainMember];

                foreach (DomainMember domainMember in domainMemberList)
                {
                    if (domainMember.Domain.Id.Equals(concept.Id) && domainMember.ArcCR.ExtendedLinkRole.Equals(sourceRole))
                    {
                        return domainMember;
                    }
                }
            }

            return null;
        }


        private bool IsPrimaryItemRootOfDRS(Concept concept)
        {
            foreach (string role in hasHypercubes.Keys)
            {
                List<HasHypercube> hasHypercubeList = hasHypercubes[role];

                foreach (HasHypercube hasHypercube in hasHypercubeList)
                {
                    if (hasHypercube.PrimaryItem.Id.Equals(concept.Id))
                    {
                        return true;
                    }
                }
            }

            return false;
        }

        private Hypercube GetHypercubeById(string id)
        {
            foreach (Hypercube hypercube in hypercubes)
            {
                if (hypercube.Concept.Id.Equals(id))
                {
                    return hypercube;
                }
            }
            return null;
        }

        private HasHypercube GetHasHypercubeById(string id)
        {
            foreach (string role in hasHypercubes.Keys)
            {
                List<HasHypercube> hasHypercubeList = hasHypercubes[role];

                foreach (HasHypercube hasHypercube in hasHypercubeList)
                {
                    if (hasHypercube.Hypercube.Concept.Id.Equals(id))
                    {
                        return hasHypercube;
                    }
                }
            }
            return null;
        }

        private Dimension GetDimensionById(string id)
        {
            foreach (Dimension dimension in dimensions)
            {
                if (dimension.Concept.Id.Equals(id))
                {
                    return dimension;
                }
            }

            return null;
        }

        private Dimension GetDimensionByDomain(Concept concept)
        {
            foreach (string role in DimensionDomains.Keys)
            {
                List<DimensionDomain> dimensionDomainList = DimensionDomains[role];

                foreach (DimensionDomain dimensionDomain in dimensionDomainList)
                {
                    if (dimensionDomain.Domain.Concept == concept)
                    {
                        return dimensionDomain.Dimension;
                    }
                }
            }

            return null;
        }

        #endregion
    }
}
